﻿using Spider.Framework.UtilityCommon;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Spider.Framework.UtilityCommon.Extensions;
using MyCrawler.Entity;
using MyCrawler.Utilyties;

namespace MyCrawler.Controls
{
    public class TinhTeCtr : ForumsCtr
    {
        private List<string> _lsCat;

        /// <summary>
        /// source của xenforo
        /// </summary>
        public TinhTeCtr()
        {
            _source = "tinhte.vn";
            _domain = "http://www.tinhte.vn/";
            _linkInit = "http://www.tinhte.vn/forums/";
            _blockId = DateTime.Now.ToString("yyyyMMddhhmmss");
            _pageLimit = -1;
        }

        /// <summary>
        /// Contructor thứ 2
        /// </summary>
        /// <param name="source">nguồn</param>
        /// <param name="linkInit">link khởi tạo</param>
        /// <param name="domain">domain gốc - có thể trùng với link khởi tạo</param>
        /// <param name="blockId">mỗi lần khởi tạo sẽ có 1 block id, chứa list các thread</param>
        public TinhTeCtr(string source, string linkInit, string domain, string blockId)
        {
            _source = source;
            _linkInit = linkInit;
            _domain = domain; // dùng cho các trang sub trở đi, vì sẽ nối trang với domain
            _blockId = blockId;

            _pageLimit = -1;
        }

        public override List<string> GetCatalogByLink()
        {
            string html = GetWebContent(_linkInit, -1);
            string boxNav = UtilityCtr.GetItemFirst(html, @"id='widget-65'>.*?<\/ul><\/div><\/div>");
            List<string> ls_L1 = UtilityCtr.GetListItem(boxNav, @"<span class='nodeTitle'>.*?<\/span>");

            _lsCat = new List<string>(); // mảng chứa các link

            for (int i = 0; i < ls_L1.Count; i++)
            {
                string link_l1 = _domain + UtilityCtr.GetItemFirst(ls_L1[i], @"href='.*?'").Replace("href='", "").Replace("'", "");

                GetCatalogByLinkNoReturn(link_l1);
            }

            return _lsCat;
        }

        /// <summary>
        /// Lấy các Forum, catagories đổ vào database
        /// </summary>
        /// <param name="link">// link của trang chứa các catagories</param>
        /// <param name="idParrent">mã id cha</param>
        private void GetCatalogByLinkNoReturn(string link)
        {
            try
            {
                string s = GetWebContent(link, -1);

                string pattLisTagA = @"<h(3|1)[\s]+class='nodeTitle modern_bottom_left'><a[\S\D]+?data-description='[\S\D]nodeDescription-[\d]+'>.*?<\/a><\/h(3|1)>";

                var lisTagA = s.GetElements(pattLisTagA, false, PatternType.Regex);

                if (lisTagA != null && lisTagA.Count > 0)
                {
                    for (int i = 0; i < lisTagA.Count; i++) // item có dạng: div data-href='tintuc/' data-order='1'
                    {
                        string linkItem = _domain + Regex.Replace(lisTagA[i], @"(<h(3|1)[\s\S]+?href=')|('[\s]+data-description='[\s\S]+)", "");

                        // kiểm tra cái link mới lấy có con hay không?
                        string sSub = GetWebContent(linkItem, -1);

                        // kiểm tra thẻ có chứa: <span class='pageNavHeader'>Trang 1 / 172</span>
                        string pattSub = @"<span[\s]+class='pageNavHeader'>.*?<\/span>";

                        bool result = Regex.IsMatch(sSub, pattSub);

                        if (result == false) // có catagories con
                        {
                            // gọi đệ quy
                            GetCatalogByLinkNoReturn(linkItem);
                        }
                        else
                        {
                            _lsCat.Add(linkItem); // đưa link vào List
                        }
                    }
                }
            }
            catch (Exception ex) { string s = ex.Message; }
        }

        public override void GetListTopic_InCatagory(string lnkCat)
        {
            try
            {
                TraceLog_Status(_source, _blockId, " + " + lnkCat);

                // lấy link của bài viết trong trang catagories
                string s = GetWebContent(lnkCat, 500);

                if (s.IsStringNullOrEmpty())
                {
                    TraceLog_Status(_source, _blockId, " --- Data null Or empty. WebClient request time out. Kiểm tra Website có bị chết hay không hay kiểm tra kết nối internet của bạn! "); // ghi log để test
                    return;
                }

                // lấy các topics tại trang đầu tiên của Catagories
                GetTopicsInPage(s, 1);

                #region [Lấy các thông số ở các trang sau]
                try
                {
                    var pattPager = s.GetElement("<span class='pageNavHeader'>[\\w\\d\\s\\/]+", false, PatternType.Regex); /*lấy danh sách đoạn code: <div data-href='forums/thiet-bi-cong-nghe.591/' data-order='8'*/
                    string sPager = pattPager.GetElement("[\\d]+$", false, PatternType.Regex);

                    int pager = Convert.ToInt32(sPager);
                    _pageLimit = -1; // khởi tạo lại trang giới hạn

                    for (int j = 2; j <= pager; j++) // duyệt từng trang lấy link
                    {
                        if (_pageLimit != -1 && j > _pageLimit) // đã tìm thấy trang giới hạn
                        {
                            break;
                        }

                        // ex =http://www.tinhte.vn/forums/tin-tuc-su-kien.10/page-4
                        string linkPager = lnkCat + "page-" + j.ToString();
                        s = GetWebContent(linkPager, -1);

                        GetTopicsInPage(s, j); // lấy các chủ đề của trang 1
                    }
                }
                catch { }
                #endregion
            }
            catch
            { }
        }

        /// <summary>
        /// lấy các topic trong từng trang
        /// </summary>
        /// <param name="linkPager"></param>
        public void GetTopicsInPage(string sHtml, int pageIndex)
        {
            try
            {
                // đưa danh sách li vào list
                var sLiTag = sHtml.GetElements(@"<li[\s]+id='thread-[\d]+'[\s\S]+?<\/li>", false, PatternType.Regex);

                if (sLiTag == null || sLiTag.Count == 0)
                {
                    TraceLog_Status(_source, _blockId, " --- không tìm thấy Topic, kiểm tra Catagorie này có thay đổi source code!"); // ghi log để test
                    return;
                }

                // với từng thẻ li bắt đầu lấy thông tin
                for (int i = 0; i < sLiTag.Count; i++)
                {
                    try
                    {
                        var lisDate = sLiTag[i].GetElements(@"[\d]+\/[\d]+\/[\d]+", false, PatternType.Regex);
                        if (lisDate.Count == 0)
                        {
                            TraceLog_Status(_source, _blockId, " --- Ngày 'last reply' không tồn tại, có thể chủ đề đã bị xóa, đã di chuyển, hay website nguồn có sự thay đổi souce code!");
                            continue;
                        }

                        if (lisDate.Count > 0)
                        {
                            // làm việc với ngày reply của topic
                            string date = lisDate[lisDate.Count - 1];
                            string[] arrDate = date.Split('/');
                            if (arrDate.Length == 3)
                            {
                                string year = arrDate[2];
                                if (!year.Contains("20"))
                                {
                                    year = "20" + arrDate[2];
                                }
                                date = year + "-" + arrDate[1] + "-" + arrDate[0];
                            }

                            var lisHour = sLiTag[i].GetElements(@"[\d]+:[\d]+", false, PatternType.Regex);
                            string hour = "00:00";

                            if (lisHour.Count > 0)
                            {
                                hour = lisHour[lisHour.Count - 1];
                            }

                            DateTime dtReply = Convert.ToDateTime(date + " " + hour);

                            if (dtReply >= _dtLimit) // ngày reply lớn hơn ngày giới hạn quét
                            {
                                // lấy link topic
                                string pattLnTopic = @"href='threads\/.*?'";
                                string linkTopic = _domain + sLiTag[i].GetElement(pattLnTopic, false, PatternType.Regex).Replace("href='", "").Replace("'", ""); // lấy đoạn code chứa nội dung các chủ đề

                                if (linkTopic.IsStringNullOrEmpty() == true)
                                {
                                    TraceLog_Status(_source, _blockId, " --- Link của topic rỗng, có thể website nguồn có sự thay đổi souce code!");
                                    continue; // chạy tới topic kế mà không quan tâm đoạn dưới
                                }

                                // lấy idtopic
                                int idGet = 0;
                                var lisNum = linkTopic.GetElements(@".[\d]+", false, PatternType.Regex);
                                if (lisNum.Count > 0)
                                {
                                    try
                                    {
                                        idGet = Convert.ToInt32(lisNum[lisNum.Count - 1].Replace(".", ""));
                                    }
                                    catch { }
                                }

                                // lấy tiêu đề
                                string subject = sLiTag[i].GetElement(@"<a href='threads.*?<\/a>", false, PatternType.Regex);
                                subject = Regex.Replace(subject, @"<.*?>", "");

                                ForumTopicEntity obj = new ForumTopicEntity();

                                obj.IdTopicGet = idGet;
                                obj.DtReply = dtReply;
                                obj.Link = linkTopic.Trim();
                                obj.TotalReply = -1; // chưa set
                                obj.Subject = subject.Trim();
                                obj.Contents = "";
                                obj.IdCatagories = 0;
                                obj.ImgAvatar = "";
                                obj.Username = "";
                                obj.View = -1; // chưa set

                                GetContentDetail(obj);
                            }
                            else
                            {
                                if (pageIndex > 1) // nếu đây là trang thứ 2 trở đi
                                {
                                    _pageLimit = pageIndex; // đánh dấu trang hiện hành này là trang giới hạn, vì các chủ để từ trang sau luôn có ngày reply nhỏ hơn ngày giới hạn
                                    break;
                                }
                            }
                        }
                    }
                    catch
                    { }

                }
            }
            catch (Exception ex) { }
        }

        /// <summary>
        /// Lấy nội dung chi tiết của 1 topuc
        /// </summary>
        /// <param name="forumTopicEntity"></param>
        public void GetContentDetail(ForumTopicEntity fr)
        {
            try
            {
                // ghi log để test
                TraceLog_Status(_source, _blockId, " --- " + fr.Link);

                string s = GetWebContent(fr.Link, 500);

                if (s.IsStringNullOrEmpty())
                {
                    TraceLog_Status(_source, _blockId, " --- --- Data null Or empty. WebClient request time out. Kiểm tra Website có bị chết hay không hay kiểm tra kết nối internet của bạn! "); // ghi log để test
                    return;
                }

                #region [Lấy tên danh mục]
                var lsNav = s.GetElements(@"class='crumb'><span>.*?<\/span>", false, PatternType.Regex);
                string cataName = "";
                if (lsNav == null || lsNav.Count == 0)
                {
                    TraceLog_Status(_source, _blockId, " --- --- Lấy tên danh mục trên thanh navigation rỗng, có thể website nguồn có sự thay đổi souce code!");
                }
                else
                {
                    cataName = lsNav[lsNav.Count - 1].Replace("class='crumb'><span>", "").Replace("</span>", "");
                }
                #endregion

                #region [Lấy content]

                // xóa đi các trích dẫn nếu có
                s = Regex.Replace(s, @"<div[\s]+class='bbCodeBlock bbCodeQuote'[\s]+data-author='[\s\S]+?'><aside>.*?<\/aside><\/div>", "");

                string pattArticle = @"<div class='messageContent'><article>.*?<\/article><\/div>";
                var lisItem = s.GetElements(pattArticle, false, PatternType.Regex);

                if (lisItem == null || lisItem.Count == 0)
                {
                    TraceLog_Status(_source, _blockId, " --- --- Bài viết và Bình luận = 0, có thể website nguồn có sự thay đổi souce code, hay ip bị block!");
                    return;
                }

                string content = Regex.Replace(lisItem[0], @"<.*?>", " ").Trim(); // xóa toàn bộ các thẻ có trong nội dung
                content = Regex.Replace(content, @"[\s]+", " ").Trim();//replace nhiều khoảng trắng thành 1 khoảng trắng

                List<string> lisCmt = new List<string>();
                for (int i = 1; i < lisItem.Count; i++) // duyệt từng trang lấy link
                {
                    string cmt = Regex.Replace(lisItem[i], @"<.*?>", " ").Trim();
                    cmt = Regex.Replace(cmt, @"[\s]+", " ");//replace nhiều khoảng trắng thành 1 khoảng trắng
                    lisCmt.Add(cmt);
                }

                #endregion

                #region [lấy bình luận từ trang số 2 trở đi - nếu có]
                try
                {
                    string sPager = s.GetElement(@"<span[\s]+class='pageNavHeader'>.*?<\/span>", false, PatternType.Regex); /*lấy danh sách đoạn code: <div data-href='forums/thiet-bi-cong-nghe.591/' data-order='8'*/

                    var arrPager = sPager.GetElements(@"[\d]+", false, PatternType.Regex);
                    int pager = Convert.ToInt32(arrPager[arrPager.Count - 1]);

                    for (int i = 2; i <= pager; i++) // duyệt từng trang lấy link
                    {
                        string lnkSub = fr.Link + "page-" + i.ToString(); // trang sau

                        string sSub = GetWebContent(lnkSub, 500);

                        // xóa đi các trích dẫn nếu có
                        sSub = Regex.Replace(sSub, @"<div[\s]+class='bbCodeBlock bbCodeQuote'[\s]+data-author='[\s\S]+?'><aside>.*?<\/aside><\/div>", "");

                        pattArticle = @"<div class='messageContent'><article>.*?<\/article><\/div>";
                        var lisItemSub = sSub.GetElements(pattArticle, false, PatternType.Regex);

                        if (lisItemSub == null || lisItemSub.Count == 0)
                        {
                            TraceLog_Status(_source, _blockId, " --- --- Error: data empty at page index " + i.ToString());
                            return;
                        }

                        for (int j = 0; j < lisItem.Count; j++) // duyệt từng trang lấy link
                        {
                            string cmtSub = Regex.Replace(lisItemSub[j], @"<.*?>", " ").Trim();
                            cmtSub = Regex.Replace(cmtSub, @"[\s]+", " ").Trim();//replace nhiều khoảng trắng thành 1 khoảng trắng

                            lisCmt.Add(cmtSub);
                        }
                    }
                }
                catch { }
                #endregion

                #region [Ghi nhận]
                ContentEntity entity = new ContentEntity();

                entity.Category = cataName;
                entity.Comments = lisCmt;
                entity.Content = content;
                entity.Id = fr.IdTopicGet;
                entity.LastModify = fr.DtReply;
                entity.Link = fr.Link;
                entity.Source = _source;
                entity.Summury = "";
                entity.Title = fr.Subject;

                // ghi log để review
                TraceLog_Status(_source, _blockId, " --- --- Comments: " + lisCmt.Count.ToString() + " -- Last modify: " + fr.DtReply.ToString("yyyy-MM-dd hh:mm:ss tt"));
                // lưu vào file json
                string file = LogFileJson(entity);
                // ghi log để review
                TraceLog_Status(_source, _blockId, " --- --- File json: " + file);

                // tăng số topic lên 1 để thực hiện việc thống kê
                _totalTopic = _totalTopic + 1;
                UtilityCtr.TraceSettingTime(_source, _timeStart, _totalTopic, _dtLimit.ToString("yyyy-MM-dd hh:mm:ss tt"));

                //ContentBO conBo = new ContentBO();

                //if (_dic == null || _dic.Count == 0 || !_dic.ContainsKey(entity.Link))
                //{
                //    // lưu vào db
                //    entity.Id = conBo.AddNew(entity); // thêm mới

                //    _dic = new Dictionary<string, long>();
                //    _dic.Add(entity.Link, entity.Id);

                //    UtilityCtr.WriteLinks(_source, entity.Id, forumTopicEntity.Link); // đưa link vào file txt, lưu tạm nó vào đấy để kiểm tra
                //    TraceLog_Status(_source, " --- --- Insert with Id: " + entity.Id.ToString()); // ghi log để test
                //}
                //else
                //{
                //    string cmt = String.Join(", ", lisCmt.ToArray());
                //    conBo.UpdateComment(entity.Link, cmt, file);

                //    TraceLog_Status(_source, " --- --- Update with Id: " + entity.Id.ToString()); // ghi log để test
                //}
                #endregion
            }
            catch (Exception ex)
            {
                TraceLog_Status(_source, _blockId, " --- --- Error: " + ex.Message); // ghi log để test
            }
        }
    }
}
